<?PHP
/**
 * OpenStation
 *
 * @CLI
 * @Application : Action.class.php
 * @Encode : 65001 Unicode ( UTF-8 NO BOM )
 * @Description : 行为控制基类 (CLI)
 * @Author : HK <hkyyang@gmail.com>
 */

abstract class Action {

    // 视图实例
    private $view;
    // 对象实例缓存
    private $_object = array();

    /**
     * 构造方法,初始化
     *
     * @final
     * @access public
     * @param $
     * @return Void
     */
    final public function __construct() {
        // 设置错误及异常处理
        set_error_handler( array( $this, 'catchError' ) );
        set_exception_handler( array( $this, 'catchException' ) );
        // 项目类库自动载入
        spl_autoload_register( array( $this, '__OpenStationAppAutoLoadCallback' ) );
    }

    /**
     * 模板变量赋值
     *
     * @access public
     * @param Array | String : $name
     * @param * : $value
     * @return Object
     */
    public function assign( $name, $value = NULL ) {
        if( empty( $name ) ) {
            return false;
        }
        $this -> LoadViewCache();
        $this -> view -> assign( $name, $value );
        return $this -> view;
    }

    /**
     * 生成静态页面
     *
     * @access public
     * @param String : $tpl, 模板名
     * @param String : $filename, 保存的文件名
     * @param String : $charset, 编码
     * @param String : $contentType, 类型
     * @return Boolean
     */
    public function toStatic( $tpl = NULL, $filename, $charset = NULL, $contentType = NULL ) {
        if( empty( $filename ) ) {
            throw_exception( Cache :: lang( 'MISSING_PARAM_EXIST' ) . ': toStatic :: "filename"' );
        }
        if( get_file_ext( $filename ) == '' ) {
            $filename .= Cache :: get( 'OPENSTATION.TEMPLATE.STATIC_EXT' );
        }
        $this -> LoadViewCache();
        $content = $this -> view -> fetch( $tpl, $charset, $contentType, FALSE );
        $savePath = dirname( $filename );
        mkdirs( $savePath );
        return file_put_contents( $filename, $content );
    }

    /**
     * auto_instance_view 方法，自动实例化视图
     *
     * @access private
     * @param $
     * @return void
     */
    private function auto_instance_view() {
        if( is_null( $this -> view ) ) {
            $cache = APP_PATH . 'Data/Build/CORE-TPL.cache.php';
            if( ! class_exists( 'View', FALSE ) && ! is_file( $cache ) ) {
                $viewClass = array(
                    OS_PATH . 'Lib/Core/View.class.php',
                    OS_PATH . 'Lib/Template/Core/OpenTPL_Parse.class.php',
                    OS_PATH . 'Lib/Template/Core/OpenTPL_Method.class.php',
                    OS_PATH . 'Lib/Template/OpenTPL.class.php',
                );
                $data = '';
                foreach( $viewClass as $f ) {
                    $data .= code_compressed( file_get_contents( $f ) );
                }
                file_put_contents( $cache, '<?PHP if( ! defined( \'OS_PATH\' ) ) exit; ' . $data . ' ?>' );
            }
            import( $cache, NULL );
            $this -> view = get_instance_of( 'View' );
        }
    }



    /**
     * __initial 方法，行为构造方法
     *
     * @override
     * @access public
     * @param $
     * @return void
     */
    public function __initial() {}

    /**
     * __finish 方法，行为析构方法
     *
     * @override
     * @access public
     * @param $
     * @return void
     */
    public function __finish() {}

    /**
     * catchError 方法，捕获错误和警告
     *
     * @access public
     * @param Integer : $errno, 错误代码
     * @param String : $msg, 错误信息
     * @param String : $file, 所在文件
     * @param Integer : $line, 行数
     * @return void
     */
    public function catchError( $errno, $msg, $file, $line ) {
        $error = $msg . ' ' . basename( $file ) . ' (' . $line . ')';
        // CLI 模式忽略警告
        switch ( $errno ) {
            case E_ERROR :
            case E_USER_ERROR : halt( $error, FALSE ); break;
        }
    }

    /**
     * catchException 方法，捕获异常
     *
     * @access public
     * @param Exception : $e
     * @return void
     */
    public function catchException( $e ) {
        throw_exception( $e -> getMessage() );
    }

    /**
     * LoadViewCache 方法，自动实例化&载入视图缓存
     *
     * @access private
     * @param $
     * @return void
     */
    private function LoadViewCache() {
        if( is_null( $this -> view ) ) {
            $cache = APP_PATH . 'Data/Build/CORE-TPL.cache.php';
            if( ! class_exists( 'View', FALSE ) && ! is_file( $cache ) ) {
                $viewClass = array(
                    OS_PATH . 'Lib/Core/View.class.php',
                    OS_PATH . 'Lib/Template/Core/OpenTPL_Parse.class.php',
                    OS_PATH . 'Lib/Template/Core/OpenTPL_Method.class.php',
                    OS_PATH . 'Lib/Template/OpenTPL.class.php',
                );
                $data = '';
                foreach( $viewClass as $f ) {
                    $data .= code_compressed( file_get_contents( $f ) );
                }
                file_put_contents( $cache, '<?PHP if( ! defined( \'OS_PATH\' ) ) exit; ' . $data . ' ?>' );
            }
            import( $cache, NULL );
            $this -> view = get_instance_of( 'View' );
        }
    }

    /**
     * loadModelCache 方法，自动实例化&载入视图缓存
     *
     * @access private
     * @param $
     * @return void
     */
    private function loadModelCache() {
        if( ! class_exists( 'Db', FALSE ) ) {
            $cache = APP_PATH . 'Data/Build/CORE-MODEL.cache.php';
            if( ! is_file( $cache ) ) {
                $data = code_compressed( file_get_contents( OS_PATH . 'Lib/Db/Db.class.php' ) );
                $data .= code_compressed( file_get_contents( OS_PATH . 'Lib/Core/Model.class.php' ) );
                file_put_contents( $cache, '<?PHP if( ! defined( \'OS_PATH\' ) ) exit; ' . $data . ' ?>' );
            }
            import( $cache, NULL );
        }
    }

    /**
     * __get魔术方法，根据别名载入内置类库，并且缓存对象实例
     *
     * @access public
     * @param String : $name, 类名称
     * @return Object
     */
    public function __get( $name ) {
        $name = strtoupper( $name );
        if( isset( $this -> _object[ $name ] ) ) {
            return $this -> _object[ $name ];
        }

        // 内置别名设置
        if( Cache :: get( 'OPENSTATION.ALIAS.' . $name ) ) {
            if( Cache :: type( 'OPENSTATION.ALIAS.' . $name, 'array' ) ) {
                $class = Cache :: get( 'OPENSTATION.ALIAS.' . $name . '.0' );
                $method = Cache :: get( 'OPENSTATION.ALIAS.' . $name . '.1' );
                call_user_func( array( $this, $method ) );
            } else if( Cache :: type( 'OPENSTATION.ALIAS.' . $name, 'string' ) && is_file( Cache :: get( 'OPENSTATION.ALIAS.' . $name ) ) ) {
                $file = basename( Cache :: get( 'OPENSTATION.ALIAS.' . $name ) );
                $class = substr( $file, 0, strpos( $file, '.' ) );
                if( ! class_exists( $class, FALSE ) ) {
                    import( Cache :: get( 'OPENSTATION.ALIAS.' . $name ) );
                }
            }
        }

        if( isset( $class ) && class_exists( $class, FALSE ) ) {
            $obj = new $class;
            $this -> _object[ $name ] = $obj;
            return $this -> _object[ $name ];
        }
        // 调用了未声明的类变量
        throw_exception( Cache :: lang( 'VARIABLE_NOT_EXIST' ) . ': "' . $name . '"' );
        return NULL;
    }

    /**
     * __call魔术方法，获取请求参数
     *
     * @access public
     * @param String : $method
     * @param Integer : $args
     * @return *
     */
    public function __call( $method, $args ) {
        // 获取当前参数, 方法形式
        if( $method == 'args' ) {
            if( count( $args ) < 1 ) {
                return Cache :: get( 'SERVER.REQUEST' );
            }
            if( isset( $args[ 0 ] ) ) {
                if( is_int( $args[ 0 ] ) ) {
                    return Cache :: get( 'SERVER.REQUEST.' . $args[ 0 ] );
                }
            }
            return NULL;
        } else {
            // 调用了未声明的类方法
           throw_exception( Cache :: lang( 'METHOD_NOT_EXIST' ) . ': ' . $method . '( ' . implode( ', ', $args ) . ' )' );
        }
    }

    /**
     * __OpenStationAppAutoLoadCallback 方法，自动载入项目类库回调方法
     *
     * @callback
     * @access public
     * @param String : $class
     * @return void
     */
    public function __OpenStationAppAutoLoadCallback( $class ) {

        // 自动载入网络应用静态类
        if( in_array( $class, array( 'Session', 'Cookie' ) ) ) {
            import( 'Lib.Net.' . $class );
            return;
        }
        // 自动载入模型基类缓存
        if( $class == 'Model' ) {
            $this -> loadModelCache();
            return false;
        }

        // 载入项目的自定义模型
        if( substr( $class, -5 ) == 'Model' ) {
            // 载入模型基类缓存
            $this -> loadModelCache();
            // 尝试在项目Model目录中搜索
            $file = search_file( Cache :: get( 'APP_PATH.MODEL' ), $class . '.class.php' );
            if( is_null( $file ) ) {
                throw_exception( Cache :: lang( 'MODEL_NOT_EXIST' ) . ': "' . $class . '"' );
            }
        // 载入项目自定义类库
        } else {
            // 尝试在项目Include目录中搜索
            $file = search_file( Cache :: get( 'APP_PATH.INCLUDE' ), $class . '.class.php' );
            // 没有搜索到文件
            if( is_null( $file ) ) {
                throw_exception( Cache :: lang( 'CLASS_NOT_EXIST' ) . ': "' . $class . '"' );
            }
        }
        import( $file );
    }
}
?>